import csv
import StringIO
import cgi
import datetime
from utils import *
from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import memcache
from google.appengine.ext.webapp.util import login_required
from table import Candidate 

class ChangeEmail (webapp.RequestHandler):

    @login_required    
    def get(self):
        wr = self.response.out.write
        wr("<html><body>")
        if users.is_current_user_admin():
            wr("""
                <script type="text/javascript">
                    function verify(){
                        old_email = document.email_change.old_email.value;
                        new_email = document.email_change.new_email.value;
                        val = confirm ("Are you sure about changing email: "+ old_email+ " to email: " + new_email+ "?" ) ;
                        return val;                    
                    }
                </script>
                
            """)
            wr("<h1 align=centre>Email Change Form</h1>")
            wr("""<form method='POST' name = 'email_change'
                    onsubmit='verify();' action='/admin/email_change'>""")
            wr("<br/><br/>")
            wr("<label for='old_email'>Select The old email</label>")
            wr("<select name='old_email'>")
            all_cand = Candidate.all().fetch(1000)
            for cand in all_cand:
                wr("<option value='%s'>%s</option>"%(cand.email,cand.email))
            wr("""            
                </select>
                <br/>
                <br/>
                <label for='new_email'>Enter the new email</label>
                <input type='text' name='new_email'/>
                <br/>
                <br/>
                <input type='submit' value='Change'/>
                </form>
            """)
            wr("<br/><br/>")
        wr("<a href='/admin/home'>Home</a>")
        wr("</body></html>")

    def post(self):
        wr = self.response.out.write
        wr("<html><body>")
        old_email = self.request.get('old_email')
        new_email = self.request.get('new_email')
        cand = Candidate.all().filter('email =',old_email.lower()).get()
        cand.email = new_email
        cand.put()        
        wr("</html></body>")
        self.redirect ("/admin/email_change")


class EvaluateAnswers(webapp.RequestHandler):

    def post(self):
        email = self.request.get ('email')
        cand = Candidate.all().filter('email =',email.lower()).get() 
        for ctr in range(len(cand.qtype)):
            #Exception occurs since we dont pass
            #the mark for passage questions
            try:
                mark = int (self.request.get ('mark%d'%ctr))
            except:
                mark = cand.prob_stud_mark[ctr]

            #Should we do this?
            #if the given mark is greater than
            #the maximum mark, should we set
            #it to the max mark?

            if mark > cand.prob_max_mark[ctr]:
                mark = cand.prob_max_mark[ctr]
            cand.prob_stud_mark[ctr] = mark            
        cand.total_stud_mark = reduce (lambda a,b: a+b, cand.prob_stud_mark)
        cand.put()
        self.redirect ('/admin/ans?%s'%(email.lower()))
        

class AnswerSheet(webapp.RequestHandler):

    @login_required
    def get(self):
        wr = self.response.out.write
        wr('<html><body>')
        if users.is_current_user_admin():
            try:
                email = self.request.query_string
                if email:
                    self.view_ans(email)             
                    return
            except Exception,e:
                pass
            wr("""<form method='POST' action='/admin/ans'>
                  <label for='email'> Enter the email address</label>
                  <select name='email'>")
            """)
            all_cand = Candidate.all().fetch(1000)
            for cand in all_cand:
                wr("<option value='%s'>%s</option>"%(cand.email,cand.email))
            wr("""            
                  </select>
                  <input type='submit' value='Answer Sheet'/>
                  </form>
            """)                          
        else:
            wr("This is not the admin id.Please sign in as admin")
            url = users.create_logout_url(self.request.uri)
            wr("<a href=%s>Logout</a>"%(url))
        wr('</body></html>')          

    def post(self):
        self.view_ans(self.request.get('email'))

    def view_ans(self,email):
        cand = Candidate.all().filter('email =',email.lower()).get() 
        wr = self.response.out.write
        wr("<form method='POST' action='/admin/eval'>")
        wr("<input type='hidden' name='email' value='%s'></input>"%email)
        wr("<b>Student's details</b><br/><br/>")
        wr('<table width=100% align=center border=1>')
        wr("<tr><td align=left><b>%s</b></td><td align=center>%s</td></tr>"%("Email",email))
        for cnt in xrange (0,len(cand.details),2):
            wr("<tr><td align=left><b>%s</b></td><td align=center>%s</td></tr>"
                    %(cand.details[cnt],
                    cand.details[cnt+1])
            )
        wr("<tr><td align=left><b>Start Time in UTC</b></td><td align=center>%s</td></tr>"%cand.test_start_time)
        wr("<tr><td align=left><b>End Time in UTC</b></td><td align=center>%s</td></tr>"%cand.test_end_time)
        wr("<tr><td align=left><b>Mark</b></td><td align=center>%s</td></tr>"%cand.total_stud_mark)
        wr("</table>")
        wr("<br/><br/>")
        for ctr in range(len(cand.qtype)):
            if cand.qtype[ctr] == 'FIBQ':
                qstrings_done = cand.qoffsets[ctr]
                wr("<br/>Question# %d %s"%(cand.qnos[ctr],unquote_html(cand.questions[qstrings_done])))
                wr('<table width=100% align=center border=1>')
                wr('<th width=35%>Expected Answer</th><th width=35%>Given Answer</th><th width=15%>Maximum Mark</th><th>Mark Scored</th>')
                wr("""<tr><td>%s</td><td>%s</td><td>%d</td><td><input type='text' style='color: BLACK; background-color: SILVER;' 
                        name='mark%d' value='%d'></input></td></tr>"""
                    %(cand.exp_ans[cand.goffsets[ctr]],
                    cand.given_ans[cand.goffsets[ctr]],
                    cand.prob_max_mark[ctr],
                    ctr,
                    cand.prob_stud_mark[ctr])
                )
                wr('</table>')
            elif cand.qtype[ctr] == 'MCQRB' or cand.qtype[ctr] == 'MCQCB':
                qstrings_done = cand.qoffsets[ctr]
                wr("<br/><p>Question# %d %s</p>"%(cand.qnos[ctr],unquote_html(cand.questions[qstrings_done])))
                noofoptn = int(cand.questions[qstrings_done+1])
                for optn in enumerate(cand.questions[qstrings_done+2:qstrings_done+2+noofoptn]):
                    wr('<br/>%d) %s'%(optn[0]+1,optn[1]))
                wr('<table width=100% align=center border=1>')
                wr('<th width=35%>Expected Answer</th><th width=35%>Given Answer</th><th width=15%>Maximum Mark</th><th>Mark Scored</th>')
                wr("""<tr><td>%s</td><td>%s</td><td>%d</td><td><input type='text' style='color: BLACK; background-color: SILVER;' 
                        name='mark%d' value='%d'></input></td></tr>"""
                    %(cand.exp_ans[cand.goffsets[ctr]],
                    cand.given_ans[cand.goffsets[ctr]],
                    cand.prob_max_mark[ctr],
                    ctr,
                    cand.prob_stud_mark[ctr])
                )
                wr('</table>')
            elif cand.qtype[ctr] == 'PASSAGE':
                qstrings_done = cand.qoffsets[ctr]
                noofquest = int(cand.questions[qstrings_done+1])
                wr("<br/>Question# %s %s"%("PASSAGE",unquote_html(cand.questions[qstrings_done])))
                wr('<table width=100% align=center border=1>')
                wr('<th width=50%>Maximum Mark</th><th>Mark Scored</th>')
                wr("<tr><td>%d</td><td>%d</td></input></td></tr>"
                    %(reduce(lambda a,b: a+b, cand.prob_max_mark[ctr+1:ctr+noofquest+1]),
                    reduce(lambda a,b: a+b, cand.prob_stud_mark[ctr+1:ctr+noofquest+1]))
                )
                wr('</table>')
            elif cand.qtype[ctr] == 'CODE':         
                qstrings_done = cand.qoffsets[ctr]
                wr("<br/>Question# %d %s"%(cand.qnos[ctr],unquote_html(cand.questions[qstrings_done])))                
                wr('<table width=100% align=center border=1>')
                wr('<th>Source Code</th>')
                wr('<tr><td>%s</td></tr>'%cgi.escape(cand.given_ans[cand.goffsets[ctr]+1]))
                wr('</table>')
                wr('<table width=100% align=center border=1>')                
                wr("<th width=50%> Expected Answer </th><th>Given Answer</th>")
                wr("<tr>")        
                wr("<td align=left>%s</th><td align=left>%s</td>"%(cand.exp_ans[cand.goffsets[ctr]],cand.given_ans[cand.goffsets[ctr]]))
                wr("</tr>")
                wr("<table>")
                wr('<table width =100% align=center border=1>')
                wr("<th width=50%> Maximum Marks</th><th>Marks Scored</th>")
                wr("<tr>")
                wr("""<td align=left>%d</th><td align=left><input type='text' style='color: BLACK; background-color: SILVER;' 
                        name='mark%d' value='%d'></input></td>"""
                    %(cand.prob_max_mark[ctr],
                    ctr,
                    cand.prob_stud_mark[ctr])
                )
                wr("</tr>")
                wr("<table>")
            else:
                wr("Unsupported Format")

        wr ("""
            <br/>
            <br/>
            <input type='submit' value='Evaluate Sheet'/>
            </form>
        """)
        wr("<br/><br/><a href='/admin/home'>Home</a>")            

class View(webapp.RequestHandler):
                        
    @login_required
    def get(self):
        wr = self.response.out.write
        wr('<html><body>')
        if users.is_current_user_admin():
            stud = Candidate.all().fetch(Candidate.all().count())
            wr('<table align=center border=1>')
            wr("""<tr>
                <th>Email</th>
                <th>Details</th>
                <th> Test Start Time</th>
                <th>Test End Time</th>
                <th>State</th>
                <th>Groups</th>
                <th>Q type</th>
                <th>No of q</th>
                <th>Q nos</th>
                <th>Q Offsets</th>
                <th>Questions</th>
                <th>Exp_ans</th>
                <th>Prob Max mark</th>
                <th>G Offsets</th>
                <th>Given Answer</th>
                <th>Problem Student mark</th>
                <th>Has_Answered</th>
                <th>Total Student Mark</th>
                <th>Ack</th>
                </tr>"""
            )
            for x in stud:
                wr("""
                    <tr>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%d</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%d</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%d</td>
                    <td>%s</td>
                    </tr>
                    """%(x.email,
                         x.details,
                         x.test_start_time,
                         x.test_end_time,
                         x.state,
                         x.group,
                         x.qtype,
                         x.total_qs,
                         x.qnos,
                         x.qoffsets,
                         x.questions,
                         x.exp_ans,
                         x.prob_max_mark,
                         x.goffsets,
                         x.given_ans,
                         x.prob_stud_mark,
                         x.has_answered,
                         x.total_stud_mark,
                         x.has_acknowledged)
                )
            wr('</table>')
            wr("<a href='/admin/home'>Home</a>")            
        else:
            wr("This is not the admin id.Please sign in as admin")
            url = users.create_logout_url(self.request.uri)
            wr("<a href=%s>Logout</a>"%(url))
        wr('</body></html>')

def clean(x):
    return x.replace("\r\n","\n").strip()

class Result(webapp.RequestHandler):

    @login_required
    def get(self):
        wr = self.response.out.write
        wr('<html><body>')
        if users.is_current_user_admin():
            cand = Candidate.all().order('-total_stud_mark').fetch(1000)
            currtime = datetime.datetime ( 2008,03,10).today()
            if len(cand):
                wr('<table align=center border=1>')
                wr('<tr><th> Start Time in UTC</th><td>%s</td>'%(str(cand[0].test_start_time)))
                wr('<tr><th> Current Time in UTC</th><td>%s</td>'%(str(currtime)))
                wr('<tr><th> End Time in UTC</th><td>%s</td>'%(str(cand[0].test_end_time)))
                wr('</table><br/><br/>')
            wr('<table align=center border=1>')
            wr("""
                <th> Sno. </th>
                <th> Email Id </th>
                <th> Marks </th>
                <th> State </th>
                <th> Acknowledged </th>
                <th>No of Q\'s Answered</th>
            """)
            cnt = 0
            for x in cand:            
                cnt += 1
                i = 0
                st = "At finalization page"
                ack = "Not yet Acknowledged"
                if x.has_acknowledged:
                    ack = "Acknowledged"
                if x.state == -1:
                    st = "Not yet Started the test"
                elif x.state == -2:
                    st = "Completed the test"                
                else:
                    if x.state<len(x.qnos) and x.qnos[x.state] == -1:
                        while ( (x.state + i) < x.total_qs and x.qnos[x.state+i] == -1):
                            i += 1                           
                    if (x.state + i) < x.total_qs:    
                        st = "At Question %d"%(x.qnos[x.state+i])
                    if (x.state + i) < x.total_qs and currtime > x.test_end_time:                
                        st = "Test Time Expired When At Question %d"%(x.qnos[x.state+i])
                    if (x.state + i) == x.total_qs:
                        st = "In submission page"
                wr("""
                    <tr><td>%d</td>
                    <td><a href = "/admin/ans?%s">%s</a></td>
                    <td>%d</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%d</td>
                </tr>"""
                        %(cnt,x.email,x.email,x.total_stud_mark,st,ack,x.has_answered.count(True))
                )
            wr('</table>')            
            wr('<br/> Please refresh to get latest results')
            wr("<br/><a href='/admin/home'>Home</a>")            
        else:
            wr("This is not the admin id.Please sign in as admin")
            url = users.create_logout_url(self.request.uri)
            wr("<br/><br/><a href=%s>Logout</a>"%(url))
        wr('</body></html>')

class Load(webapp.RequestHandler):

    @login_required
    def get(self):
        wr = self.response.out.write
        wr('<html><body>')
        if users.is_current_user_admin():
            if Candidate.all().count():
                wr("<h1> WARNING! - Already data is there in database</h1>")
            wr("""
                <html>
                <head>
                <script src="http://www.google.com/jsapi"></script>
                <script>
                  // Load jQuery
                  google.load("jquery", "1");
                  google.setOnLoadCallback(function() {
                      $('#submit').bind("click", function() {

                            var mask = $('#form')

                            var input = document.forms[0].input.value

                            if (input) {

                                    var s = input.split("~!@~!@~!@~!@~!@~!@~!@~!@")

                                    var i = -1

                                    var successFn = function() {
                                        ++i;
                                        if (i == s.length) {
                                            mask.html("Sent all");
                                        }
                                        else if (i > 0) {
                                            mask.html("Student detail Sent: " + i + " Sending: " + (i+1) + " " + s[i]);
                                        } else {
                                            mask.html("Submitting Now: " + "Sending: " + (i+1) + " " + s[i].replace(/^\s*/, "").replace(/\s*$/, "") + "]</pre>");
                                        }

                                        var dataD = "cand=" + escape(s[i].replace(/^\s*/, "").replace(/\s*$/, ""))
                                        if (i < s.length) {
                                            $.ajax({
                                                type: "POST",
                                                url: "load",
                                                data: dataD, 
                                                success: successFn,
                                                failure: function() {
                                                   mask.html("Error sending: " + i);
                                                }
                                            });
                                        }
                                    }
                                    
                                    successFn()                                 

                            }

                        });
                    });
                </script>
                </head>
                <body>
                <form id='form'>
                    <textarea name="input" rows=30 cols=100></textarea>
                </form>
                <a href="#" id='submit'>Submit</a><br/><a href='/admin/home'>Home</a>
                </body>
                </html>           
            """) 
        else:
            wr("This is not the admin id.Please sign in as admin")
            url = users.create_logout_url(self.request.uri)
            wr("<br/><br/><a href=%s>Logout</a>"%(url))
        wr('</body></html>')

    def post(self):
        contents = cgi.escape(self.request.get('cand')).strip().replace ("\r\n","\n")
        for x in csv.reader(StringIO.StringIO(contents)):
            if not x :
                continue
            email = x[0].lower()            
            if Candidate.all().filter('email =',email).count():
                cand = Candidate.all().filter('email =',email).get()
                if cand.state != -1:
                    continue
                #Use the Fields to be preserved here               
                ack = cand.has_acknowledged
            else:
                cand = Candidate ( )
                ack = False
            cnt = 0
            cand.email,cnt = (email,cnt+1)
            count,cnt = (x[cnt],cnt+1) #count for the number of name value pairs
            cand.details,cnt = cluster(cnt, 2*int(count), x[cnt:])
            cand.instructions,cnt = (x[cnt],cnt+1)
            cand.test_start_time,cnt = (eval("datetime.datetime ("+str(map( int, x[cnt].split(':')))[1:-1]+")"),cnt+1) #Converts date time string to
            cand.test_end_time,cnt = (eval("datetime.datetime ("+str(map( int, x[cnt].split(':')))[1:-1]+")"),cnt+1)   #datetime in python
            cand.state = -1
            cand.has_acknowledged = ack 
            count,cnt = (x[cnt],cnt+1) #count for the number of grops, types, questions.
            cand.group,cnt = cluster(cnt, count, x[cnt:])
            cand.qtype,cnt = cluster(cnt, count, x[cnt:])
            questions=[]
            for y in cand.qtype:
                questions,cnt = parseqns (questions, y, x, cnt)
            cand.questions = map (db.Text, questions)
            str_qnos,cnt = cluster(cnt, count, x[cnt:])
            cand.qnos = map(int, str_qnos)
            cand.total_qs,cnt = (int(x[cnt]),cnt+1)
            cand.exp_ans,cnt = filexpans(cand.qtype,cnt,x)             
            str_prob_max_mark,cnt = cluster(cnt, count, x[cnt:])
            cand.prob_max_mark = map(int, str_prob_max_mark)
            str_offsets,cnt = cluster(cnt, count, x[cnt:])
            cand.qoffsets = map(int, str_offsets)
            str_offsets,cnt = cluster(cnt, count, x[cnt:])
            cand.goffsets = map(int, str_offsets)
            cand.given_ans = fillans(cand.qtype) 
            cand.prob_stud_mark = [0 for z in range(int(count))]
            cand.has_answered = [False for z in range(int(count))]
            cand.total_stud_mark = 0
            cand.put()
            


def filexpans(qtype,cnt,value):
    #We dont add any expected or given answer for PASSAGE questions
    ans=[]
    for type in qtype:
        if type == 'CODE':
            #Expected output and a dummy value
            ans.extend(map(db.Text,value[cnt:cnt+2]))
            cnt+= 2
        if type == 'MCQCB' or type == 'MCQRB' or type == 'FIBQ':
            ans.append(db.Text(value[cnt]))
            cnt+= 1            
        if type == 'PASSAGE':
            cnt+= 1
    return(ans,cnt)            

def fillans(qtype):
    ans=[]
    for type in qtype:
        if type == 'MCQCB' or type == 'MCQRB' or type == 'FIBQ':
            ans.append ( db.Text('') )
        if type == 'CODE':
            ans.append ( db.Text('') )
            ans.append ( db.Text('') )
    return ans            
        
def parseqns (questions, type, values, cnt):
    #defualt action of reading the question is enough for FIBQ questions
    q,cnt = (clean(values[cnt]),cnt+1)
    questions.append(q)
    if type == 'CODE':
        #Added the input set and delimiters.
        ans_delim,cnt = (values[cnt:cnt+2],cnt+2)
        questions.extend(ans_delim)
    if type == 'MCQCB' or type == 'MCQRB':
        count,cnt = (values[cnt],cnt+1) #count for the number of options
        questions.append(count)
        q,cnt = cluster(cnt, count, values[cnt:]) 
        questions.extend(q)
    if type == 'PASSAGE':
        count,cnt = (values[cnt],cnt+1)
        questions.append(count)
    return (questions,cnt)        
        
def cluster (currn, count, values):
    return ( map(db.Text, map(clean, values[:int(count)])), currn+int(count))

class Home(webapp.RequestHandler):

    @login_required
    def get(self):
        wr = self.response.out.write
        wr('<html><body>')
        if users.is_current_user_admin():
            wr("""
                <h1><div align='centre'>Admin Console</div></h1>
                <a href='/admin/load'>Load</a><br/><br/>
                <a href='/admin/view'>View</a> (CAUTION: Use It only when debugging.)<br/><br/>
                <a href='/admin/ans'>Answers</a><br/><br/>
                <a href='/admin/res'>Results</a><br/><br/>
                <a href='/admin/email_change'>Replace Emailid</a><br/><br/>
               """)
            url = users.create_logout_url(self.request.uri)
            wr("<a href=%s>Logout</a>"%(url))
        else:
            wr("This is not the admin id.Please sign in as admin<br/>")
            url = users.create_logout_url(self.request.uri)
            wr("<a href=%s>Logout</a>"%(url))   
        wr('</body></html>')

application = webapp.WSGIApplication(
                                     [('/admin/load', Load),
                                      ('/admin/view', View),
                                      ('/admin/ans', AnswerSheet),
                                      ('/admin/res', Result),
                                      ('/admin/home', Home),
                                      ('/admin/eval', EvaluateAnswers),
                                      ('/admin/email_change', ChangeEmail)],
                                     debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()


